
/****************************************************************************
**
** Copyright (C) 2004-2008 VATATA.com . All rights reserved.
**
** This file is the part of the Miniutil Poject of VATATA.com.
** Vatata's miniutil library is lightweight and portable (for linux
** and Windows). The C++ Class Library included Threadpool, Dll danymic loading, 
** General socket application model and tcp server, httpserver/servlet, etc. 
** It is a pratical utility disigned for who don't want learn the Big C++ 
** Developing Platform, such as  Boost or ACE.
**
** This file may be used under the terms of the GNU General Public
** License versions 2.0 or 3.0 as published by the Free Software
** Foundation and appearing in the files LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file.  Alternatively you may (at
** your option) use any later version of the GNU General Public
** License if such license has been publicly approved by VATATA.com.
** (or its successors, if any) and the Miniutil Project Aministrators. 
**
** Please review the following information to ensure GNU General
** Public Licensing requirements will be met:
** http://www.gnu.org/licenses/lgpl.html. If you are unsure which 
** license is appropriate for your use, please review the following 
** information: http://code.google.com/p/miniutil/ or contact 
** http://www.vatata.com.
**
** In addition, as a special exception, VATATA.com, as the sole
** copyright holder for Miniutil Project, grants users of VATATA
** P2P Platform the right to release and package with the related 
** libraries without the source code.
**
** This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE. vatata reserves all rights not expressly
** granted herein.
**
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
**
****************************************************************************/



#include <miniutil/data.h>

#include <stdio.h>
#include <stdlib.h>

using namespace miniutil;
using namespace miniutil::data;

bool  storage::_save( const char * d, int len, const char * filename )
{
	FILE* f = miniutil::fileu::open(filename, "wb");
	if ( f == NULL )
		return false;

//	fseek( f, 0, 0);
	size_t wl = fwrite( d, 1, len, f );
	fclose( f );

	if ( wl <= 0 )
		return false;
	return true;
}


size_t storage::_info( const char * filename )
{
	fileu f(filename);
	if (  !f.isExist() || ! f.isFile() )
		return 0;

//	printf("_info file %s len %d\n", filename, f.getLength() );

	return f.getLength();
}

size_t storage::_load( char *d , size_t len , const char * filename )
{
	FILE * f = fopen(filename, "rb");
	if ( f== NULL )
		return 0;

//	fseek( f, 0, 0);
	size_t rl = fread( (void *)d, 1, len, f );
//	size_t allreadlen = rl;
//	while( allreadlen < len )
//	{
//		printf(" %d ", rl);
//		fseek( f, allreadlen, 0 );
//		rl = fread( (void *)(d+allreadlen) , 1, len - allreadlen, f );
//		if ( rl <= 0 ) break;
//		allreadlen += rl;
//	}
//printf("_load file res allreadlen len %d for %d\n", allreadlen, len );
	fclose( f );

	return rl;

}

storage::storage( const char * basename ) : basedir(basename) , maxid(0)
{
	if ( ! basedir.isExist() )
		diru::mkdir( basename );
}

storage * storage::getStorage( const char * basename )
{
	storage * pstorage = new storage( basename );
	if (  pstorage->basedir.isDir() )
		return pstorage;
	delete pstorage;
	return NULL;
}

storage::~storage()
{
}

void storage::_id2filename( char * fname, long id )
{
#ifdef WIN32
	sprintf( fname, "%s\\%d", basedir.getName().c_str(), id );
#else
	sprintf( fname, "%s/%d", basedir.getName().c_str(), id );
#endif
}


void storage::clear()
{
	miniutil::diru sdir( basedir.getName() );

	string f = sdir.first();
	while( f.length() > 0 )
	{
		if ( f != "." && f != ".." )
		{
			fileu::remove( f );
		}
		f = sdir.next();
	}

	fileu::remove( basedir.getName() );
}


bool storage::save( const char * d, int len, long id )
{
	if ( id > this->maxid )
		maxid = id + 1;

	char fname[2000];
	_id2filename( fname, id );

	return storage::_save(d, len, fname );
}

long storage::save( const char * d, int len )
{
	long cid = ++ this->maxid ;

	return save( d,len, cid );
}

char * storage::load_and_malloc( long id )
{
	char fname[2000];
	_id2filename( fname, id );

	size_t len = storage::_info( fname );
	if ( len <= 0 )
		return NULL ;
	char * buf = (char *)malloc( len );
	size_t nlen = storage::_load( buf, len, fname );
	if ( nlen == len )
		return buf;
	free( buf );
	return NULL;
}

size_t storage::info( long id )
{
	char fname[2000];
	_id2filename( fname, id );
	return storage::_info( fname );
}

size_t storage::load( char * d ,long id )
{
	char fname[2000];
	_id2filename( fname, id );

	size_t len = storage::_info( fname );
	if ( len <= 0 )
		return 0 ;

	size_t nlen = storage::_load( d, len, fname );
	if ( nlen == len )
		return nlen;

	return 0;
}


